#include "edt.hpp"
#include "dimacs.hpp"
#include <ostream>

void init_probleme(probleme& pb)
{
    pb.enseigne = vector< set<int> >(pb.nb_enseignants);
    pb.salles = vector< set<int> >(pb.nb_cours);
    pb.indisponibilites = vector< set<int> >(pb.nb_enseignants);
}

void affiche_solution_html(ostream& out, solution& sol, probleme& pb)
{
    affectation vide;
    vide.enseignant = -1;
    vide.cours = -1;
    vide.salle = -1;
    vide.creneau = -1;
    vector<affectation> salles_vides(pb.nb_salles, vide);
    vector< vector<affectation> > table(pb.nb_creneaux, salles_vides);
    for(auto it = sol.cbegin(); it != sol.cend(); ++it)
    {
        table[it->creneau][it->salle] = *it;
    }
    out << "<html><head><title>Solution</title></head><body><h1>Solution</h1>" << endl;
    out << "<table><thead><tr>";
    for(int i = 0; i < pb.nb_salles; ++i)
    {
        out << "<th>Salle " << i << "</th>";
    }
    out << "</thead>" << endl << "<tbody>" << endl;
    for(int i = 0; i < pb.nb_creneaux; ++i) {
        out << "<tr>";
        for(int j = 0; j < pb.nb_salles; ++j) {
            out << "<td>";
            if (table[i][j].enseignant == -1)
            {
                out << " X ";
            }
             else {
                out << "Cours: " << table[i][j].cours;
                out << "<br/>Enseignant: " << table[i][j].enseignant;
            }
            out << "</td>";
        }
        out << "</tr>" << endl;
    }
    out << "</tbody></table>" << endl;
    out << "</html>" << endl;
}


/*----------- Exercices sur la représentation d'un emploi du temps-------------- */

   // Coder la fonction void init_lits(const probleme& pb, lit_edt& vars)
   // permettant d'initialiser cette structure en fonction du problème
    // (i.e. en fonction du nombre de salles, d'enseignants, etc)

//  permettant d'initialiser cette structure en fonction du problème (i.e. en fonction du nombre de salles, d'enseignants, etc)
void init_lits(const probleme& pb, lit_edt& vars)
{
     int variable =0;

     // en fonction du nombre d'enseignant
     for(int i=0; i<pb.nb_cours; i++)
     {
         for(int j=0; j<=pb.nb_enseignants; j++)
         {
             vars.Cr_En[i][j]= var2lit(variable,true);
             variable=variable+2;
         }
     }

     // en fonction du nombres de salles
     for(int g=0; g<pb.nb_cours; g++)
     {
         for(int h=0; h<=pb.nb_salles; h++)
         {
             vars.Cr_Sal[g][h]=var2lit(variable,true);
             variable=variable+2;
         }
     }

     // en fonction du nombres de creneau
     for(int a=0; a<pb.nb_cours; a++)
     {
         for(int b=0; b<=pb.nb_creneaux; b++)
         {
             vars.Cr_Cx[a][b]=var2lit(variable,true);
             variable=variable+2;
         }
     }





    /*
    int variable=1;
    vars.Cr_Cx.resize(probleme.nb_creneaux);
    for(int i=0; i<=probleme.nb_cours; i++)
    {
        for(int j=0;j<=probleme.nb_creneaux; j++)
        {
            vars.Cr_Cx[i][j]=var2lit(variable,true);
        }

    }
    variable++;

    vars.Cr_En.resize(probleme.nb_cours);
    for(int g=0; g<=probleme.nb_cours; g++)
    {
        for(int h=0;h<=probleme.nb_salles; h++)
        {
              vars.Cr_En[g][h]=var2lit(variable,true);
        }

    }
      variable++;

    vars.Cr_Sal.resize(probleme.nb_creneaux);
    for(int a=0; a<=probleme.nb_creneaux; a++)
    {
        for(int b=0;b<=probleme.nb_salles; b++)
        {
               vars.Cr_Sal[a][b]=var2lit(variable,true);
        }

    }
     variable++;*/
}


/* ------------------Exercices sur les contraintes implicites --------------------------*/

// Génère la clause qui exprime que deux cours ne peuvent avoir lieu
// en même temps au même endroit.
void cours_salle_creneau(ostream& out, const lit_edt& vars, int cours1, int cours2, int salle, int creneau)
{
    // On definit la clause à retourner
    cls_t Clause_Salle_Creneau;

    // On definit les salles et les creneaux
     int Cours_Salle1 = vars.Cr_Sal[cours1][salle];
     int Cours_Salle2 = vars.Cr_Sal[cours2][salle];
     int Cours_Creneaux1 = vars.Cr_Cx[cours1][creneau];
     int Cours_Creneaux2 = vars.Cr_Cx[cours2][creneau];

     // On cherche à ce qu'il n'y est pas la meme salle et le meme creneau
     // pour cela nous mettons les 4 litteral dont on a besoin pour evaluer l'unicité d'un cours
     // dans une seule salle et un seul creneau
     Clause_Salle_Creneau.insert(neg(Cours_Salle1));
     Clause_Salle_Creneau.insert(neg(Cours_Salle2));
     Clause_Salle_Creneau.insert(neg(Cours_Creneaux1));
     Clause_Salle_Creneau.insert(neg(Cours_Creneaux2));

     //! A verifier
    ecrit_clause_dimacs(out, Clause_Salle_Creneau);

    cout<< "OK"<<endl;
}


// qui génère ces clauses pour toutes les combinaisons possibles de cours, salles et créneaux.
void cours_salle_creneau(ostream& out, const probleme& pb, const lit_edt& vars)
{
    int salle,creneau,cm_1,cm_2;
	for(salle = 0; salle <pb.nb_salles; salle++)
	{
		for(creneau = 0; creneau <pb.nb_creneaux; creneau++)
		{
			for(cm_1 = 0; cm_1 <pb.nb_cours; cm_1 ++)
			{
				for(cm_2= cm_1+1; cm_2 <pb.nb_cours; cm_2++)
				{
					cours_salle_creneau(out, vars, cm_1, cm_2, salle, creneau);
				}
			}
		}
	}

    cout<< " OK "<<endl;
}


// Implémenter la fonction
//void cours_enseignant_creneau(ostream& out, const lit_edt& v, int , int , int , int)
//qui génère la clause qui exprime que deux cours ne peuvent avoir le même enseignant pendant le même créneau.
//L'utiliser pour coder la fonction void cours_enseignant_creneau(ostream& out, const probleme& pb, const lit_edt& vars)
// qui génère ces clauses pour toutes les combinaisons possibles de cours, enseignants et créneaux.
void cours_enseignant_creneau(ostream& out, const lit_edt& vars, int cours1, int cours2, int enseignant, int creneau)
{
    cout<< " a faire thierno "<<endl;

}

void cours_enseignant_creneau(ostream& out, const probleme& pb, const lit_edt& vars)
{
    cout<< " a faire thierno "<<endl;
}

/*--------------------- ----------------------------------------------*/


void ecrit_cnf_probleme(ostream& out, probleme& pb)
{
    out << "A implementer" << endl;
}

// A coder
solution construit_solution(set<lit_t>& modele, probleme& pb)
{
    solution sol;
    return sol;
}

